﻿/// <summary>
/// <Filename>: Motion_3DMAX.cs
/// Author: Jiang Xiaolong
/// Created: 2015.01.30
/// Version: 1.0
/// Company: Sunnytech
/// Function: 3DMAX表格运动信息处理类
///
/// Changed By:
/// Modification Time:
/// Discription:
/// <summary>
using UnityEngine;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Collections;
using Motion.MotionPlatform.Tools;
using System.Reflection;

namespace Motion.MotionPlatform
{
	public class MaxMotion : IMotion
	{
		//默认为Active
		public CurrentState State
		{
			get { return _state; }
			set { _state = value; }
		}
		private CurrentState _state = CurrentState.Active;
		//速率
		public float SpeedRate
		{
			get { return Motion_Data.SpeedRate; }
			set { Motion_Data.SpeedRate = value; }
		}
		//暂停状态
		public bool PauseControl
		{
			get { return Motion_Data.PauseControl; }
			set { Motion_Data.PauseControl = value; }
		}
		//时间参数
		//正常速率时间
		public float StandardTime
		{
			get { return _standardTime; }
			set { _standardTime = value; }
		}
		private float _standardTime = 0f;
		//运动开始时间
		public float StartTime
		{
			get { return _startTime; }
			set { _startTime = value; }
		}
		private float _startTime = 0f;
		//运动结束时间
		public float EndTime
		{
			get { return _endTime; }
			set { _endTime = value; }
		}
		private float _endTime = 0f;

		//动画宿主
		public GameObject AnimationParent = null;
		//动画名称
		public string AnimationName = "";

		//当前3dMax的进度,0为开始,1为结束
		//float CurrentProgress;
		public float RecordSpeed;

		//PC2动画:动画物体名,起始帧,结束帧
		public List<string> PC2_Animation_Name = new List<string>();
		public List<int> PC2_Animation_StartFrame = new List<int>();
		public List<int> PC2_Animation_EndFrame = new List<int>();
        //float FPS = 30f;

		//是否顺序播放
		public bool isOrder = true;

		public void Init()
		{

			if (AnimationParent != null)
			{
				if (isOrder)
				{
					AnimationParent.animation.Play(AnimationName);
					AnimationParent.animation[AnimationName].speed = RecordSpeed;//恢复播放速度
				}
				else
				{
					AnimationParent.animation.Play(AnimationName);
					AnimationParent.animation[AnimationName].normalizedTime = 1f;
					RecordSpeed = -1f;
					AnimationParent.animation[AnimationName].speed = RecordSpeed;//恢复播放速度
				}
				//AnimationParent.animation.Play(AnimationName);
				//AnimationParent.animation[AnimationName].speed = RecordSpeed;//恢复播放速度
				//CurrentProgress = 0f;
			}
		}

		//暂停控制
		public void Pause(bool play_status)  //接口方法
		{
			if (play_status)
			{//暂停
				RecordSpeed = AnimationParent.animation[AnimationName].speed;//记录当前播放速度
				AnimationParent.animation[AnimationName].speed = 0f;//当前播放速度设置为0
			}
			else
			{//播放
				AnimationParent.animation[AnimationName].speed = RecordSpeed;//恢复播放速度
			}
		}

		//设置3dMax动画的进度
		public void setCurrentProgress(bool isStart)
		{

			//3dmax动画最初状态
			if (isStart)
			{
				if (isOrder)
				{
					RecordSpeed = AnimationParent.animation[AnimationName].speed;//记录当前播放速度
					AnimationParent.animation[AnimationName].speed = -1f;
					AnimationParent.animation.Play(AnimationName);
					AnimationParent.animation[AnimationName].normalizedTime = 0f;

					Type _t = Motion_TypeGet.MotionTypeGet("ReflectionManager");
					if (!MotionPlatformData.st_ReflectionManager && _t != null)
					{
						MotionPlatformData.st_ReflectionManager = (MonoBehaviour)GameObject.FindObjectOfType(_t);
					}
					if (MotionPlatformData.st_ReflectionManager && _t != null)
					{
						MethodInfo methodInfo = _t.GetMethod("Reflection3DMAX");
						BindingFlags flag = BindingFlags.Public | BindingFlags.Instance;
						object[] para = new object[] { PC2_Animation_Name.ToArray(), isStart };
						methodInfo.Invoke(MotionPlatformData.st_ReflectionManager, flag, Type.DefaultBinder, para, null);
					}
				}
				else
				{

				}
			}
			//3dmax动画结束状态
			else
			{
				if (isOrder)
				{
					RecordSpeed = AnimationParent.animation[AnimationName].speed;//记录当前播放速度
					AnimationParent.animation[AnimationName].speed = 1f;
					AnimationParent.animation.Play(AnimationName);
					AnimationParent.animation[AnimationName].normalizedTime = 1f;

					Type _t = Motion_TypeGet.MotionTypeGet("ReflectionManager");
					if (!MotionPlatformData.st_ReflectionManager && _t != null)
					{
						MotionPlatformData.st_ReflectionManager = (MonoBehaviour)GameObject.FindObjectOfType(_t);
					}
					if (MotionPlatformData.st_ReflectionManager && _t != null)
					{
						MethodInfo methodInfo = _t.GetMethod("Reflection3DMAX");
						BindingFlags flag = BindingFlags.Public | BindingFlags.Instance;
						object[] para = new object[] { PC2_Animation_Name.ToArray(), isStart };
						methodInfo.Invoke(MotionPlatformData.st_ReflectionManager, flag, Type.DefaultBinder, para, null);
					}
				}
				else
				{

				}
			}

			//st_manager.StartCoroutine(st_manager.stopMax(AnimationParent, AnimationName));
		}

		//速率控制
		public void ChangeRate(float current_rate, float current_time)  //接口方法
		{
			//过程速率改变
			//根据速率改变终止时间和播放速度
			EndTime = current_time + (EndTime - current_time) * SpeedRate / current_rate;
			if (PauseControl)
			{
				RecordSpeed = RecordSpeed * current_rate / SpeedRate; //记录修改后的播放速度
			}
			else
			{
				AnimationParent.animation[AnimationName].speed
					= AnimationParent.animation[AnimationName].speed * current_rate / SpeedRate;
			}

		}

		//通用运动驱动函数
		public void Move(float current_time, float speed_rate, float delta_time)  //接口方法
		{
			Type _t = Motion_TypeGet.MotionTypeGet("ReflectionManager");
			if (!MotionPlatformData.st_ReflectionManager && _t != null)
			{
				MotionPlatformData.st_ReflectionManager = (MonoBehaviour)GameObject.FindObjectOfType(_t);
			}
			if (MotionPlatformData.st_ReflectionManager && _t != null)
			{
				MethodInfo methodInfo = _t.GetMethod("Reflection3DMAXMove");
				BindingFlags flag = BindingFlags.Public | BindingFlags.Instance;
				object[] para = new object[] { PC2_Animation_Name.ToArray(), PC2_Animation_StartFrame.ToArray(), PC2_Animation_EndFrame.ToArray(), AnimationParent, AnimationName };
				methodInfo.Invoke(MotionPlatformData.st_ReflectionManager, flag, Type.DefaultBinder, para, null);
			}
		}

		//时间控制
		public bool TimesUp(float current_time)
		{
			if (current_time > EndTime)
				return true;
			else
				return false;
		}

		//后处理，主要是位置修正
		public void PostProcess()
		{
			if (AnimationParent != null)
			{
				AnimationParent.animation.Stop(AnimationName);
			}
			setCurrentProgress(false);
		}
	}


	/// <summary>
	/// 3DMAX运动信息提取管理类，相当于工厂；
	/// </summary>
	public class Motion_3DMAXInfoManager : IMotionInfoManager
	{
		/// <summary>
		/// 信息获取函数，用反射的方式创建Tips相应的解析类；
		/// </summary>
		/// <param name="motion_symbol">当前运动标识符；</param>
		/// <param name="data_row">当前传入的Excel数据行；</param>
		/// <param name="row_id">当前行对应ID号；</param>
		/// <param name="group_table">当前Group数据表；</param>
		/// <param name="motion_list">简单运动类列表；</param>
		/// <param name="complex_motion_list">复合运动类列表；</param>
		/// <returns>解析是否正确；</returns>
		public bool InfoGet(string motion_symbol, int state, DataRow data_row, string row_id, DataTable group_table, IList<IMotion> motion_list, IList<IList<IMotion>> complex_motion_list)
		{
			string motionTypeID = "ONLY";
			if (Motion_Data.MotionFunctionAllow(motion_symbol, motionTypeID, state))
			{
				if (Motion_Data.MotionFunctionClassDic[motion_symbol].ContainsKey(motionTypeID))
				{
					Type _t = Motion_TypeGet.MotionTypeGet("Motion.MotionPlatform." + Motion_Data.MotionFunctionClassDic[motion_symbol][motionTypeID]);
					//实例化相应的解析类
					IMotionFunctionInfo infoInstance = (IMotionFunctionInfo)Activator.CreateInstance(_t);

					////将Excel中参数转换成参数表里面的数据
					//Motion_Compute.ExcelDataAnalysis(ref data_row);
					return infoInstance.InfoGet(data_row, row_id, group_table, motion_list, complex_motion_list);
				}
				else
				{
					Debug.LogError("3DMAX运动标志符：" + motionTypeID + "，不含有该运动标志符对应的解析类，请询问相关程序猿！");
					return false;
				}
			}
			else
			{
				return true;
			}
		}
	}

	/// <summary>
	/// 3DMAX运动；
	/// </summary>
	public class Motion_3DMAX_Only : IMotionFunctionInfo
	{

		public bool InfoGet(DataRow data_row, string row_id, DataTable group_table, IList<IMotion> motion_list, IList<IList<IMotion>> complex_motion_list)
		{
			MaxMotion _maxMotion = new MaxMotion();

			bool is_right = true;
			Hashtable cameraHashTable = new Hashtable();

			string objName = (string)data_row[2].ToString();
			_maxMotion.AnimationParent = GameObject.Find(objName);
			if (_maxMotion.AnimationParent == null)
			{
				is_right = false;
				if (Motion_Data.isEditor)
				{
					Debug.LogError(ErrorLocation.Locate("3DMAX", "OBJNAME", row_id) + "，动画所在物体名称错误！");
				}
				return false;
			}
			_maxMotion.AnimationName = (string)data_row[3].ToString();
			cameraHashTable.Add("AnimationName", _maxMotion.AnimationName);
			cameraHashTable.Add("State", "End");
			//时间确定
			try
			{
				_maxMotion.StandardTime = _maxMotion.AnimationParent.animation[_maxMotion.AnimationName].length;
				_maxMotion.AnimationParent.animation[_maxMotion.AnimationName].speed = 1.0f;
			}
			catch
			{
				is_right = false;
				if (Motion_Data.isEditor)
				{
					Debug.LogError(ErrorLocation.Locate("3DMAX", "ANINAME", row_id) + "，动画名字错误！");
				}
				return false;
			}
			string customTimeStr = (string)data_row[4].ToString();
			if (customTimeStr != "")
			{
				_maxMotion.StandardTime = Motion_Compute.FloatConversion(customTimeStr, ref is_right);
				if (!is_right || _maxMotion.StandardTime == 0)
				{
					if (Motion_Data.isEditor)
					{
						Debug.LogError(ErrorLocation.Locate("3DMAX", "Time", row_id) + "，自定义动画播放时长设置错误！");
					}
					return false;
				}
				_maxMotion.AnimationParent.animation[_maxMotion.AnimationName].speed =
					_maxMotion.AnimationParent.animation[_maxMotion.AnimationName].length / _maxMotion.StandardTime;
			}

			//根据速率改变终止时间和播放速度
			_maxMotion.EndTime = _maxMotion.StandardTime / _maxMotion.SpeedRate;
			_maxMotion.AnimationParent.animation[_maxMotion.AnimationName].speed
				= _maxMotion.AnimationParent.animation[_maxMotion.AnimationName].speed * _maxMotion.SpeedRate;

			_maxMotion.RecordSpeed = _maxMotion.AnimationParent.animation[_maxMotion.AnimationName].speed;//记录当前播放速度
			_maxMotion.AnimationParent.animation[_maxMotion.AnimationName].speed = 0f;//当前播放速度设置为0

			////倒着播放
			//if (data_row[5].ToString() == "back")
			//{
			//	_maxMotion.isOrder = false;
			//}

			//PC2动画
			if ((string)data_row[5].ToString() != "")
			{
				string[] pc2_1 = data_row[5].ToString().Split('|');
				string[] pc2_2 = data_row[6].ToString().Split('|');
				string[] pc2_3 = data_row[7].ToString().Split('|');
				_maxMotion.PC2_Animation_Name.Clear();
				_maxMotion.PC2_Animation_StartFrame.Clear();
				_maxMotion.PC2_Animation_EndFrame.Clear();
				for (int i = 0; i < pc2_1.Length; i++)
				{
					//Debug.Log(i+","+pc2_1[i]+","+pc2_2[i]+","+pc2_3[i]);

					if (GameObject.Find(pc2_1[i]) == null)
					{
						is_right = false;
						if (Motion_Data.isEditor)
						{
							Debug.LogError(ErrorLocation.Locate("3DMAX", "PC2OBJNAME", row_id) + "，PC2动画所在物体名称错误！");
						}
						return false;
					}
					int num = 0;
					if (!int.TryParse(pc2_2[i], out num))
					{
						is_right = false;
						if (Motion_Data.isEditor)
						{
							Debug.LogError(ErrorLocation.Locate("3DMAX", "PC2STARTFRAME", row_id) + "，PC2动画所在起始帧填写错误！");
						}
						return false;
					}
					else
					{
						if (int.Parse(pc2_2[i]) < 0)
						{
							is_right = false;
							if (Motion_Data.isEditor)
							{
								Debug.LogError(ErrorLocation.Locate("3DMAX", "PC2STARTFRAME", row_id) + "，PC2动画所在起始帧必须大于或等于0！");
							}
							return false;
						}
					}

					if (!int.TryParse(pc2_3[i], out num))
					{
						is_right = false;
						if (Motion_Data.isEditor)
						{
							Debug.LogError(ErrorLocation.Locate("3DMAX", "PC2EndFRAME", row_id) + "，PC2动画所在结束帧填写错误！");
						}
						return false;
					}

					if (int.Parse(pc2_2[i]) >= int.Parse(pc2_3[i]))
					{
						is_right = false;
						if (Motion_Data.isEditor)
						{
							Debug.LogError(ErrorLocation.Locate("3DMAX", "PC2STARTFRAME", row_id) + "，PC2动画所在起始帧必须小于结束帧！");
						}
						return false;
					}
					int pc2_frames = int.Parse(pc2_3[i]) - int.Parse(pc2_2[i]);
					float pc2_time = pc2_frames / _maxMotion.AnimationParent.animation[_maxMotion.AnimationName].clip.frameRate;

					Type _t = Motion_TypeGet.MotionTypeGet("ReflectionManager");
					if (!MotionPlatformData.st_ReflectionManager && _t != null)
					{
						MotionPlatformData.st_ReflectionManager = (MonoBehaviour)GameObject.FindObjectOfType(_t);
					}
					if (MotionPlatformData.st_ReflectionManager && _t != null)
					{
						MethodInfo methodInfo = _t.GetMethod("Reflection3DMAXMaxTime");
						BindingFlags flag = BindingFlags.Public | BindingFlags.Instance;
						object[] para = new object[] { pc2_1[i] };
						object maxTime = methodInfo.Invoke(MotionPlatformData.st_ReflectionManager, flag, Type.DefaultBinder, para, null);
						if (Mathf.Abs(pc2_time - (float)maxTime) > 0.01f)
						{
							is_right = false;
							if (Motion_Data.isEditor)
							{
								Debug.LogError(ErrorLocation.Locate("3DMAX", "PC2STARTFRAME", row_id) + "，PC2动画所在起始帧结束帧差值不能刚好播完PC2动画！");
							}
							return false;
						}
					}

					float pc2_endtime = int.Parse(pc2_3[i]) / _maxMotion.AnimationParent.animation[_maxMotion.AnimationName].clip.frameRate;
					if (pc2_endtime > _maxMotion.AnimationParent.animation[_maxMotion.AnimationName].length)
					{
						is_right = false;
						if (Motion_Data.isEditor)
						{
							Debug.LogError(ErrorLocation.Locate("3DMAX", "PC2EndFRAME", row_id) + "，PC2动画所在起始帧结束帧不能在父物体的动画内播完PC2动画！");
						}
						return false;
					}

					_maxMotion.PC2_Animation_Name.Add(pc2_1[i]);
					_maxMotion.PC2_Animation_StartFrame.Add(int.Parse(pc2_2[i]));
					_maxMotion.PC2_Animation_EndFrame.Add(int.Parse(pc2_3[i]));
				}
			}

			//记录3DMAX的状态
			if (Motion_Data.isEditor && MotionPlatformData.currentMotion == MotionPlatformState.Teaching)
			{
				Type _t = Motion_TypeGet.MotionTypeGet("ReflectionManager");
				if (!MotionPlatformData.st_ReflectionManager && _t != null)
				{
					MotionPlatformData.st_ReflectionManager = (MonoBehaviour)GameObject.FindObjectOfType(_t);
				}
				if (MotionPlatformData.st_ReflectionManager && _t != null)
				{
					MethodInfo methodInfo = _t.GetMethod("ReflectionAddState");
					BindingFlags flag = BindingFlags.Public | BindingFlags.Instance;
					object[] para = new object[] { MotionPlatformData.excelName, MotionPlatformData.mainRowNumber + 2, "State_Max", _maxMotion.AnimationParent.name, cameraHashTable };
					methodInfo.Invoke(MotionPlatformData.st_ReflectionManager, flag, Type.DefaultBinder, para, null);
				}
			}

			motion_list.Add(_maxMotion);

			//自动装配处理
			if (Motion_Data.IsAutoAssemble)
			{
				//用于记录自动装配信息
				string[] autoAssembleContents = new string[data_row.Table.Columns.Count];
				for (int i = 0; i < data_row.Table.Columns.Count; i++)
				{
					autoAssembleContents[i] = data_row[i].ToString();
				}

				//TODO: 如果有PC2动画会出错
				if (autoAssembleContents[5].ToUpper() == "BACK")
				{
					autoAssembleContents[5] = "";
				}
				else
				{
					autoAssembleContents[5] = "back";
				}

				//更新当前行
				Motion_AutoAssemblyAndTime.AutoUpdate(autoAssembleContents, "3DMAX", 1);
			}

			return true;
		}

	}
}
